package org.nanotek.persistence.jpa;

import java.util.List;

import javax.enterprise.inject.Default;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.nanotek.Base;
import org.nanotek.persistence.DAOException;
import org.nanotek.persistence.jpa.JpaDAO;
/**
 * http://docs.oracle.com/middleware/1213/toplink/jpa-extensions-reference/queryhints.htm
 * @author josecanovamauger
 *
 * @param <T>
 */
@Default
public class BrainzBaseDAO <T extends Base<?>> extends JpaDAO<T>{

	public BrainzBaseDAO() {
		super();
	}

	public BrainzBaseDAO(Class<T> baseClass, EntityManager entityManager) {
		super(baseClass, entityManager);
	}

	public BrainzBaseDAO(Class<T> baseClass) {
		super(baseClass);
	}

	
	
	public List<?> findByValue (String jpql , String value)
	{ 
		Query query = entityManager.createQuery(jpql).setParameter("value", value);
		return query.getResultList();
	}
	
	@Override
	public Long countRecords() {
		
		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		CriteriaQuery<Long> countQuery = criteriaBuilder.createQuery(Long.class);
		countQuery.select(criteriaBuilder.count(countQuery.from(getBaseClass())));
		
//		Metamodel m = entityManager.getMetamodel();
//		EntityType<T> baseType = m.entity(getBaseClass());
//		CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(getBaseClass());
//		Root<T> baseRoot  = criteriaQuery.from(baseType);
//		Expression<? extends Number> expression = criteriaBuilder.count(baseRoot);
//		criteriaQuery.select(criteriaQuery.from(baseType));
		
//		int pageSize = 10;
//		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
//		CriteriaQuery<Foo> criteriaQuery = criteriaBuilder.createQuery(Foo.class);
//		Root<Foo> from = criteriaQuery.from(Foo.class);
//		CriteriaQuery<Foo> select = criteriaQuery.select(from);
//		TypedQuery<Foo> typedQuery = entityManager.createQuery(select);
//		typedQuery.setFirstResult(0);
//		typedQuery.setMaxResults(pageSize);
//		List<Foo> fooList = typedQuery.getResultList();
		
//		int pageNumber = 1;
//		int pageSize = 10;
//		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
//		 
//		CriteriaQuery<Long> countQuery = criteriaBuilder.createQuery(Long.class);
//		countQuery.select(criteriaBuilder.count(countQuery.from(Foo.class)));
//		Long count = entityManager.createQuery(countQuery).getSingleResult();
//		 
//		CriteriaQuery<Foo> criteriaQuery = criteriaBuilder.createQuery(Foo.class);
//		Root<Foo> from = criteriaQuery.from(Foo.class);
//		CriteriaQuery<Foo> select = criteriaQuery.select(from);
//		Root<T> from = criteriaQuery.from(getBaseClass());
 
//		TypedQuery<Foo> typedQuery = entityManager.createQuery(select);
//		while (pageNumber < count.intValue()) {
//		    typedQuery.setFirstResult(pageNumber - 1);
//		    typedQuery.setMaxResults(pageSize);
//		    System.out.println("Current page: " + typedQuery.getResultList());
//		    pageNumber += pageSize;
//		}
		return entityManager.createQuery(countQuery).getSingleResult();
	}

	@Override
	public List<T> loadAll() {

		if (baseClass == null)
			throw new DAOException("No Persistent Class found");
		
		return  entityManager.createQuery("select c from " + getBaseClass().getName() + " c ").getResultList() ;
	}

	public CriteriaQuery <T> getCriteriaQuery () 
	{ 
		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		return criteriaBuilder.createQuery(getBaseClass());
	}

	@Override
	public List<T> listRecords(Integer firstResult, Integer maxResults) {
		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(getBaseClass());
		Root<T> from = criteriaQuery.from(getBaseClass());
		CriteriaQuery<T> select = criteriaQuery.select(from);
		select.orderBy(criteriaBuilder.asc(from.get("id")));
		TypedQuery<T> typedQuery = entityManager.createQuery(select);
		typedQuery.setFirstResult(firstResult);
		typedQuery.setMaxResults(maxResults);
		return  typedQuery.getResultList();
	}
	
}
